package com.gitee.chili.leisure.base;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * RedisService
 *
 * @author week solider
 * @since 2020.09.15
 */
@Slf4j
@Service
public class RedisService {


    @Autowired
    private StringRedisTemplate redisTemplate;


    /**
     * 存储
     *
     * @param key   键
     * @param value 值
     */
    public void set(final String key, String value) {
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        opsForValue.set(key, value);
    }

    /**
     * 根据{@code key} 获取 {@code value}
     *
     * @param key 缓存的键
     */
    public String get(final String key) {
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        return opsForValue.get(key);
    }

    /**
     * 给键设置过期时间
     *
     * @param key     需要设置的键
     * @param timeout 过期时间 (单位： 秒)
     */
    public void expire(final String key, Long timeout) {
        redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 获取缓存剩余时间
     */
    public Long getExpire(final String key) {
        return redisTemplate.getExpire(key);
    }

    /**
     * 写入缓存
     *
     * @param timeout 超时时间 (单位：秒)
     */
    public void set(final String key, String value, Long timeout) {
        try {
            set(key, value);
            expire(key, timeout);
        } catch (Exception e) {
            log.error("redis set exception：{}", e.getMessage(), e);
        }
    }

    /**
     * 移除缓存信息
     *
     * @param key 缓存的键
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 对指定的{@code key} 进行增量 (此处只是 +1)
     * <p>
     * 需要注意的是，如果添加的 {@code key} 不存在，那么 {@code key} 的值会被初始化为 0
     * 而后对这个 {@code key} 进行 {@code increment} 操作，如果值的类型不是数字，则抛出
     * 异常
     *
     * @param key 需要增量的键
     */
    public void increment(String key) {
        try {
            redisTemplate.opsForValue().increment(key);
        } catch (Exception e) {
            log.error("对 {} 进行增量时，发生异常， errMsg: {}", key, e.getMessage(), e);
        }
    }


    /**
     * 将哈希值{@code filed}的{@code value}增加 1
     *
     * @param key   hash 键
     * @param filed 字段
     */
    public void incrementHash(String key, Object filed) {
        try {
            redisTemplate.opsForHash().increment(key, filed, 1L);
        } catch (Exception e) {
            log.error("对 {} 进行增量时，发生异常， errMsg: {}", key, e.getMessage(), e);
        }
    }

    /**
     * 存储一个名为{@code key}的{@code hash}结构的{@code value}
     *
     * @param key   hash 键
     * @param filed 字段
     */
    public void setHash(String key, Object filed, String value) {
        try {
            redisTemplate.opsForHash().put(key, filed, value);
        } catch (Exception e) {
            log.error("对 {} 进行增量时，发生异常， errMsg: {}", key, e.getMessage(), e);
        }
    }


    /**
     * 获取 {@code hash} 的值
     *
     * @param key   键
     * @param filed 字段
     */
    public long getHash(String key, Object filed) {
        if (hasKey(key)) {
            Object value = redisTemplate.opsForHash().get(key, filed);
            if (Objects.nonNull(value)) {
                return Long.parseLong(value.toString());
            }
        }
        return -1;
    }

    /**
     * 判断缓存中是否有对应的value
     */
    public boolean hasKey(final String key) {
        Boolean hasKey = redisTemplate.hasKey(key);
        return hasKey != null && hasKey;
    }

}
